package thread.wang_bao_ling.c30;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * ThreadLocal OOM示例
 * VM Args:-Xms1024m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError
 */
public class TestThreadLocalOOM {
    private static final ThreadPoolExecutor myExecutor;
    private static int tCount=1;
    static {
        //堆大小设置为了1024M，老年代大概680M(2/3)，所以10个线程每个线程中ThreadLocal占用100m,则会内存溢出，如果调整成5个线程的样子就不会内存溢出（因为同一个线程再次设置ThreadLocal会覆盖之前的值）
        myExecutor = new ThreadPoolExecutor(10, 10, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<>(400), (r)-> {
            Thread thread = new Thread(r,"my-executor-thread" + tCount);
            tCount++;
            return thread;
        });
    }
    private static ThreadLocal<User> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) throws InterruptedException {
        while (true) {
            executeMyWordByPool();
            //executeMyWord(); //通过临时线程去设置ThreadLocal不会内存溢出
            System.gc();
            System.out.println("System.gc()");
            Thread.currentThread().sleep(1000);
        }
    }

    /**
     * 通过线程池去设置ThreadLocal
     */
    public static void executeMyWordByPool(){
        myExecutor.execute(new MyWork());
    }

    /**
     * 通过临时线程去设置ThreadLocal
     */
    public static void executeMyWord(){
        new Thread(new MyWork()).start();
    }

    public static class MyWork implements Runnable {
        @Override
        public void run() {
            threadLocal.set(new User());
            System.out.println("set success");
        }
    }

    public static class User{
        byte[]  M_100= new byte[1024*1024*100];//100M
    }

}
